﻿using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Xml;
using FastShell.Common.Model;
using Renci.SshNet.Sftp;

namespace FastShell.Common
{
    public static class FileUtils
    {
        /// <summary>    
        /// 创建节点    
        /// </summary>    
        /// <param name="xmlDoc">xml文档</param>    
        /// <param name="parentNode">Xml父节点</param>    
        /// <param name="name">节点名</param>    
        /// <param name="value">节点值</param>    
        ///   
        public static XmlNode CreateNode(XmlDocument xmlDoc, XmlNode parentNode, string name, string value)
        {
            //创建对应Xml节点元素
            XmlNode node = xmlDoc.CreateNode(XmlNodeType.Element, name, null);
            if (value != null)
            {
                node.InnerText = value;
            }            
            parentNode.AppendChild(node);
            return node;
        }
        /// <summary>
        /// 创建配置文件
        /// </summary>
        public static void CreateConfigFile(XmlDocument xmlHostConfig, string configName)
        {
            //创建类型声明节点  
            XmlNode node = xmlHostConfig.CreateXmlDeclaration("1.0", "utf-8", "");
            xmlHostConfig.AppendChild(node);
            //创建Xml根节点  
            XmlNode root = xmlHostConfig.CreateElement("Hosts");
            xmlHostConfig.AppendChild(root);

            XmlNode host = xmlHostConfig.CreateElement("Host");
            CreateAttribute(xmlHostConfig, host, "Id", "1");
            CreateAttribute(xmlHostConfig, host, "ParentId", "0");
            CreateAttribute(xmlHostConfig, host, "Name", "远程主机");
            CreateAttribute(xmlHostConfig, host, "Type", "folder");

            root.AppendChild(host);

            //将文件保存到指定位置
            xmlHostConfig.Save(configName);
        }
        public static string getHostIcon(string type)
        {
            return type.Equals("folder") ? "/Assets/folder.png" : type.Equals("linux") ? "/Assets/host.png" : "/Assets/win.png";
        }
        /// <summary>
        /// 创建属性
        /// </summary>
        /// <param name="xmlHostConfig"></param>
        /// <param name="host"></param>
        /// <param name="name"></param>
        /// <param name="value"></param>
        public static void CreateAttribute(XmlDocument xmlHostConfig, XmlNode host, string name, string value)
        {
            XmlAttribute attr = xmlHostConfig.CreateAttribute(name);
            attr.InnerText = value;
            host.Attributes.Append(attr);
        }
        /// <summary>
        /// 加载host配置信息
        /// </summary>
        /// <param name="rootId"></param>
        /// <returns></returns>
        public static HostTreeModel LoadHostData(XmlDocument xmlHostConfig, string rootId)
        {

            XmlNode root = xmlHostConfig.SelectSingleNode("/Hosts/Host[@Id='" + rootId + "']");
            HostTreeModel data = new HostTreeModel();
            data.Id = rootId;
            data.Name = root.SelectSingleNode("@Name").InnerText;
            data.Type = root.SelectSingleNode("@Type").InnerText;
            data.Icon = getHostIcon(data.Type);

            XmlNodeList nodeList = xmlHostConfig.SelectNodes("Hosts/Host[@ParentId='" + rootId + "']");
            ObservableCollection<HostTreeModel> subList = new ObservableCollection<HostTreeModel>();
            foreach (XmlNode item in nodeList)
            {
                string subId = item.SelectSingleNode("@Id").InnerText;
                HostTreeModel data1 = LoadHostData(xmlHostConfig,subId);
                data1.Parent = data;
                subList.Add(data1);
            }
            data.Children = subList;
            return data;
        }

        /// <summary>
        /// 新增
        /// </summary>
        /// <param name="val"></param>
        /// <param name="configName"></param>
        /// <returns></returns>
        public static void AddHostConfig(XmlDocument xmlHostConfig, HostConfig val, string configName)
        {
            XmlNode root = xmlHostConfig.SelectSingleNode("/Hosts");
            XmlNode node = FileUtils.CreateNode(xmlHostConfig, root, "Host", null);
            FileUtils.CreateAttribute(xmlHostConfig, node, "Id", val.Id);
            FileUtils.CreateAttribute(xmlHostConfig, node, "ParentId", val.ParentId);
            FileUtils.CreateAttribute(xmlHostConfig, node, "Name", val.Name);
            FileUtils.CreateAttribute(xmlHostConfig, node, "Type", val.Type);
            if (!val.Type.Equals("folder"))
            {
                FileUtils.CreateAttribute(xmlHostConfig, node, "Host", val.Host);
                FileUtils.CreateAttribute(xmlHostConfig, node, "Port", val.Port.ToString());
                FileUtils.CreateAttribute(xmlHostConfig, node, "UserName", val.UserName);
                FileUtils.CreateAttribute(xmlHostConfig, node, "Password", val.Password);
                FileUtils.CreateAttribute(xmlHostConfig, node, "KeyFilePassphrase", val.KeyFilePassphrase);
                FileUtils.CreateAttribute(xmlHostConfig, node, "KeyFilePath", val.KeyFilePath);
            }
            xmlHostConfig.Save(configName);
        }
        /// <summary>
        /// 更新
        /// </summary>
        /// <param name="val"></param>
        /// <returns></returns>
        public static void UpdateHostConfig(XmlDocument xmlHostConfig, HostConfig val, string configName)
        {
            XmlNode node = xmlHostConfig.SelectSingleNode("/Hosts/Host[@Id='" + val.Id + "']");
            node.SelectSingleNode("@Name").InnerText = val.Name;
            node.SelectSingleNode("@Type").InnerText = val.Type;
            if (!val.Type.Equals("folder"))
            {
                node.SelectSingleNode("@Host").InnerText = val.Host;
                node.SelectSingleNode("@Port").InnerText = val.Port.ToString();
                node.SelectSingleNode("@UserName").InnerText = val.UserName;
                node.SelectSingleNode("@Password").InnerText = val.Password;
                node.SelectSingleNode("@KeyFilePassphrase").InnerText = val.KeyFilePassphrase;
                node.SelectSingleNode("@KeyFilePath").InnerText = val.KeyFilePath;
            }
            xmlHostConfig.Save(configName);
        }
        /// <summary>
        /// 获取config
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public static HostConfig GetHostConfig(XmlDocument xmlHostConfig, string id)
        {
            HostConfig config = new HostConfig();
            XmlNode node = xmlHostConfig.SelectSingleNode("/Hosts/Host[@Id='" + id + "']");
            config.Id = id;
            config.ParentId = node.SelectSingleNode("@ParentId").InnerText;
            config.Name = node.SelectSingleNode("@Name").InnerText;
            config.Type = node.SelectSingleNode("@Type").InnerText;
            if (!config.Type.Equals("folder"))
            {
                config.Host = node.SelectSingleNode("@Host").InnerText;
                config.Port = int.Parse(node.SelectSingleNode("@Port").InnerText);
                config.UserName = node.SelectSingleNode("@UserName").InnerText;
                config.Password = node.SelectSingleNode("@Password").InnerText;
                config.KeyFilePassphrase = node.SelectSingleNode("@KeyFilePassphrase").InnerText;
                config.KeyFilePath = node.SelectSingleNode("@KeyFilePath").InnerText;
            }
            return config;
        }
        /// <summary>
        /// 组装file对象
        /// </summary>
        /// <param name="a"></param>
        /// <returns></returns>
        public static FileTreeModel getFileInfo(SftpFile a)
        {
            return new FileTreeModel()
            {
                Name = a.Name,
                FullName = a.FullName,
                Icon = a.IsSymbolicLink || a.IsDirectory ? "/Assets/folder.png" : "/Assets/file.png",
                Type = a.IsSymbolicLink || a.IsDirectory ? "文件夹" : "",
                LastTime = a.LastAccessTime.ToString("yyyy-MM-dd HH:mm:ss"),
                Length = getFileLengthString(a),
                Permissions = getFilePermissionString(a),
                UserGroup = a.UserId + "/" + a.GroupId,
                SftpFile = a
            };
        }

        private static string getFileLengthString(SftpFile a)
        {
            if (a.IsSymbolicLink || a.IsDirectory)
            {
                return "";
            }
            return a.Length > 1024 * 1024 * 1024 ?
                Math.Round(a.Length / 1024d / 1024d / 1024d, 1) + "GB" : a.Length > 1024 * 1024 ?
                Math.Round(a.Length / 1024d / 1024d, 1) + "MB" : a.Length > 1024 ?
                Math.Round(a.Length / 1024d, 0) + "KB" : a.Length + "B";
        }

        private static string getFilePermissionString(SftpFile a)
        {
            string pStr = a.IsDirectory || a.IsSymbolicLink ? "d" : "-";
            pStr += a.OwnerCanRead ? "r" : "-";
            pStr += a.OwnerCanWrite ? "w" : "-";
            pStr += a.OwnerCanExecute ? "x" : "-";

            pStr += a.GroupCanRead ? "r" : "-";
            pStr += a.GroupCanWrite ? "w" : "-";
            pStr += a.GroupCanExecute ? "x" : "-";

            pStr += a.OthersCanRead ? "r" : "-";
            pStr += a.OthersCanWrite ? "w" : "-";
            pStr += a.OthersCanExecute ? "x" : "-";

            return pStr;
        }
    }
}
